#include "./i2c/i2c.h"

#ifdef USE_SOFTWARE_I2C

void i2c_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	I2C_SCL_GPIO_CLK_ENABLE(); 
	I2C_SDA_GPIO_CLK_ENABLE();
	
	GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN;
	GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
	
	GPIO_SetBits(I2C_SCL_GPIO_PORT, I2C_SCL_GPIO_PIN);
	GPIO_SetBits(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PIN);
}

uint8_t I2C_SDA_Read(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PIN);
	delay_us(1);
	return BitValue;
}

void I2C_Start(void)
{
	SCL(1);
	SDA(1);
	SDA(0);
	SCL(0);
}

void I2C_Stop(void)
{
	SDA(0);
	SCL(1);
	SDA(1);
}

void I2C_SendByte(uint8_t Byte)
{
	for(uint8_t i = 0; i < 8; i++)
	{
		SDA(Byte & (0x80 >> i));
		SCL(1);
		SCL(0);
	}
}

uint8_t I2C_ReceiveByte(void)
{
	uint8_t Byte = 0x00;
	SDA(1);
	
	for(uint8_t i = 0; i < 8; i++)
	{
		SCL(1);
		if(I2C_SDA_Read() == 1){Byte |= (0x80 >> i);}
		SCL(0);
	}
	
	return Byte;
}

void I2C_SendAck(uint8_t AckBit)
{
	SDA(AckBit);
	SCL(1);
	SCL(0);
}

uint8_t I2C_ReceiveAck(void)
{
	uint8_t AckBit;
	
	SDA(1);
	SCL(1);
	AckBit = I2C_SDA_Read();
	SCL(0);
	
	return AckBit;
}

void Check_DeviceAddress(uint8_t Addr)
{
	I2C_Start();
	I2C_SendByte(Addr);
	uint8_t Ack = I2C_ReceiveAck();
	I2C_Stop();
	
//	if(Ack == 0)
//	{
//		printf("0x%2X is the write address of this device.\r\n", Addr);
//	}
//	else
//	{
//		printf("0x%2X is not the write address of this device.\r\n", Addr);
//	}	
}

void I2C_WriteReg(uint8_t DeviceAddress, uint8_t RegAddress, uint8_t Data)
{
	I2C_Start();
	I2C_SendByte(DeviceAddress);
	I2C_ReceiveAck();
	I2C_SendByte(RegAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

uint8_t I2C_ReadReg(uint8_t DeviceAddress, uint8_t RegAddress)
{
	uint8_t Data;
	I2C_Start();
	I2C_SendByte(DeviceAddress);
	I2C_ReceiveAck();
	I2C_SendByte(RegAddress);
	I2C_ReceiveAck();
	
	
	I2C_Start();
	I2C_SendByte(DeviceAddress | 0x01);
	I2C_ReceiveAck();
	Data = I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	
	return Data;
}

#else

void i2c_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure;
	
	I2Cx_SCL_GPIO_CLK_ENABLE(); 
	I2Cx_SDA_GPIO_CLK_ENABLE();
	
	GPIO_InitStructure.GPIO_Pin = I2Cx_SCL_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = I2Cx_SDA_GPIO_PIN;
	GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStructure);
		
	I2Cx_CLK_ENABLE();
	
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_ClockSpeed = 50000;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_Init(I2CX, &I2C_InitStructure);
	
	I2C_Cmd(I2CX, ENABLE);
}

void WaitEvent(I2C_TypeDef* I2C_SELECT, uint32_t I2C_EVENT)
{
	uint32_t Timeout = 10000;
	
	while(I2C_CheckEvent(I2C_SELECT, I2C_EVENT) != SUCCESS)
	{
		Timeout--;
		if(Timeout == 0)
		{
			break;
		}
	}
}

void I2C_WriteReg(uint8_t DeviceAddress, uint8_t RegAddress, uint8_t Data)
{
	I2C_GenerateSTART(I2CX, ENABLE);
	WaitEvent(I2CX, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2CX, DeviceAddress, I2C_Direction_Transmitter);
	WaitEvent(I2CX, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	
	I2C_SendData(I2CX, RegAddress);
	WaitEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
	
	I2C_SendData(I2CX, Data);
	WaitEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
	
	I2C_GenerateSTOP(I2CX, ENABLE);
}

uint8_t I2C_ReadReg(uint8_t DeviceAddress, uint8_t RegAddress)
{
	uint8_t Data;
	
	I2C_GenerateSTART(I2CX, ENABLE);
	WaitEvent(I2CX, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2CX, DeviceAddress, I2C_Direction_Transmitter);
	WaitEvent(I2CX, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	
	I2C_SendData(I2CX, RegAddress);
	WaitEvent(I2CX, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
	
	I2C_GenerateSTART(I2CX, ENABLE);
	WaitEvent(I2CX, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2CX, DeviceAddress, I2C_Direction_Receiver);
	WaitEvent(I2CX, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
	
	I2C_AcknowledgeConfig(I2CX, DISABLE);
	I2C_GenerateSTOP(I2CX, ENABLE);
	
	WaitEvent(I2CX, I2C_EVENT_MASTER_BYTE_RECEIVED);
	Data = I2C_ReceiveData(I2CX);
	
	I2C_AcknowledgeConfig(I2CX, ENABLE);
	
	return Data;
}

#endif
